/*
 * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.corba.se.spi.presentation.rmi;

import javax.rmi.CORBA.Tie;

import org.omg.CORBA.portable.Delegate;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.CORBA.portable.OutputStream;

import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAManager;
import org.omg.PortableServer.Servant;

import org.omg.PortableServer.POAPackage.WrongPolicy;
import org.omg.PortableServer.POAPackage.ServantNotActive;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;

import org.omg.CORBA.ORB;

import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;

// XXX Getting rid of this requires introducing an ObjectAdapterManager abstraction
// as an interface into the OA framework.
import com.sun.corba.se.impl.oa.poa.POAManagerImpl;

/** Provide access to stub delegate and type id information
 * independent of the stub type.  This class exists because
 * ObjectImpl does not have an interface for the 3 delegate and
 * type id methods, so a DynamicStub has a different type.
 * We cannot simply change ObjectImpl as it is a standard API.
 * We also cannot change the code generation of Stubs, as that
 * is also standard.  Hence I am left with this ugly class.
 */
public abstract class StubAdapter {
    private StubAdapter() {
    }

    private static ORBUtilSystemException wrapper = ORBUtilSystemException.get(CORBALogDomains.RPC_PRESENTATION);

    public static boolean isStubClass(Class cls) {
        return (ObjectImpl.class.isAssignableFrom(cls)) || (DynamicStub.class.isAssignableFrom(cls));
    }

    public static boolean isStub(Object stub) {
        return (stub instanceof DynamicStub) || (stub instanceof ObjectImpl);
    }

    public static void setDelegate(Object stub, Delegate delegate) {
        if (stub instanceof DynamicStub)
            ((DynamicStub) stub).setDelegate(delegate);
        else if (stub instanceof ObjectImpl)
            ((ObjectImpl) stub)._set_delegate(delegate);
        else
            throw wrapper.setDelegateRequiresStub();
    }

    /** Use implicit activation to get an object reference for the servant.
     */
    public static org.omg.CORBA.Object activateServant(Servant servant) {
        POA poa = servant._default_POA();
        org.omg.CORBA.Object ref = null;

        try {
            ref = poa.servant_to_reference(servant);
        } catch (ServantNotActive sna) {
            throw wrapper.getDelegateServantNotActive(sna);
        } catch (WrongPolicy wp) {
            throw wrapper.getDelegateWrongPolicy(wp);
        }

        // Make sure that the POAManager is activated if no other
        // POAManager state management has taken place.
        POAManager mgr = poa.the_POAManager();
        if (mgr instanceof POAManagerImpl) {
            POAManagerImpl mgrImpl = (POAManagerImpl) mgr;
            mgrImpl.implicitActivation();
        }

        return ref;
    }

    /** Given any Tie, return the corresponding object refernce, activating
     * the Servant if necessary.
     */
    public static org.omg.CORBA.Object activateTie(Tie tie) {
        /** Any implementation of Tie should be either a Servant or an ObjectImpl,
         * depending on which style of code generation is used.  rmic -iiop by
         * default results in an ObjectImpl-based Tie, while rmic -iiop -poa
         * results in a Servant-based Tie.  Dynamic RMI-IIOP also uses Servant-based
         * Ties (see impl.presentation.rmi.ReflectiveTie).
         */
        if (tie instanceof ObjectImpl) {
            return tie.thisObject();
        } else if (tie instanceof Servant) {
            Servant servant = (Servant) tie;
            return activateServant(servant);
        } else {
            throw wrapper.badActivateTieCall();
        }
    }

    /** This also gets the delegate from a Servant by
     * using Servant._this_object()
     */
    public static Delegate getDelegate(Object stub) {
        if (stub instanceof DynamicStub)
            return ((DynamicStub) stub).getDelegate();
        else if (stub instanceof ObjectImpl)
            return ((ObjectImpl) stub)._get_delegate();
        else if (stub instanceof Tie) {
            Tie tie = (Tie) stub;
            org.omg.CORBA.Object ref = activateTie(tie);
            return getDelegate(ref);
        } else
            throw wrapper.getDelegateRequiresStub();
    }

    public static ORB getORB(Object stub) {
        if (stub instanceof DynamicStub)
            return ((DynamicStub) stub).getORB();
        else if (stub instanceof ObjectImpl)
            return (ORB) ((ObjectImpl) stub)._orb();
        else
            throw wrapper.getOrbRequiresStub();
    }

    public static String[] getTypeIds(Object stub) {
        if (stub instanceof DynamicStub)
            return ((DynamicStub) stub).getTypeIds();
        else if (stub instanceof ObjectImpl)
            return ((ObjectImpl) stub)._ids();
        else
            throw wrapper.getTypeIdsRequiresStub();
    }

    public static void connect(Object stub, ORB orb) throws java.rmi.RemoteException {
        if (stub instanceof DynamicStub)
            ((DynamicStub) stub).connect((com.sun.corba.se.spi.orb.ORB) orb);
        else if (stub instanceof javax.rmi.CORBA.Stub)
            ((javax.rmi.CORBA.Stub) stub).connect(orb);
        else if (stub instanceof ObjectImpl)
            orb.connect((org.omg.CORBA.Object) stub);
        else
            throw wrapper.connectRequiresStub();
    }

    public static boolean isLocal(Object stub) {
        if (stub instanceof DynamicStub)
            return ((DynamicStub) stub).isLocal();
        else if (stub instanceof ObjectImpl)
            return ((ObjectImpl) stub)._is_local();
        else
            throw wrapper.isLocalRequiresStub();
    }

    public static OutputStream request(Object stub, String operation, boolean responseExpected) {
        if (stub instanceof DynamicStub)
            return ((DynamicStub) stub).request(operation, responseExpected);
        else if (stub instanceof ObjectImpl)
            return ((ObjectImpl) stub)._request(operation, responseExpected);
        else
            throw wrapper.requestRequiresStub();
    }
}
